using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;

namespace [%NAMESPACE%]
{
    public class Choice : ContainerBase
    {
        #region Constructors
        public Choice(ItemBase p_parentItem, string p_fieldName, bool p_fillInChoice, string p_valueString, string[] p_choices, bool p_emptyAllowed)
            : base(p_parentItem, p_fieldName, p_emptyAllowed)
        {
            if (p_parentItem == null) throw new PointBridgeEx("Choice constructor: p_parentItem is null.");
            if (p_fieldName == null) throw new PointBridgeEx("Choice constructor: p_fieldName is null.");

            partOfMultiSelect = false;
            parentMultiSelect = null;
            fillInChoice = p_fillInChoice;

            choices = p_choices;

            _valueString = p_valueString;
        }
        public Choice(MultiChoice p_parentMultiSelect, string p_valueString, string[] p_choices)
            : base(null, null, false)
        {
            if (p_parentMultiSelect == null) throw new PointBridgeEx("Choice constructor: p_parentMultiSelect is null.");

            partOfMultiSelect = true;
            parentMultiSelect = p_parentMultiSelect;
            fillInChoice = p_parentMultiSelect.fillInChoice;

            choices = p_choices;

            _valueString = p_valueString;
        }
        #endregion

        #region Methods
        public override void SetEmpty()
        {
            if (partOfMultiSelect == true) throw new PointBridgeEx("Choice.SetEmpty(): SetEmpty cannot be called for objects that are part of Multi-Select.");

            _valueString = null;

            //either update itself or ask parent to update everyhting
            if (partOfMultiSelect != true) ForceUpdate();
            else parentMultiSelect.ForceUpdate();
        }
        public void ChangeSelection(int newSelectedChoicesIndex)
        {
            if (newSelectedChoicesIndex == -1)
            {
                SetEmpty();
                return;
            }
            if (newSelectedChoicesIndex < 0 || newSelectedChoicesIndex >= choices.Length) throw new PointBridgeEx("Choice.ChangeSelection(): newSelectedChoicesIndex (" + newSelectedChoicesIndex + ") is outside of bounds of choices array.");
            ChangeSelection(choices[newSelectedChoicesIndex]);
        }
        public void ChangeSelection(string newValueString)
        {
            if (newValueString == null)
            {
                SetEmpty();
                return;
            }
            if (ValidateChoiceString(newValueString) == false) throw new PointBridgeEx("Choice.ChangeSelection(): '" + newValueString + "' is not a valid selection. Consider using Choice.ChangeSelectionToCustomString() method if this is intended.");
            ChangeSelectionNoValidation(newValueString);
        }
        public void ChangeSelectionToCustomString(string newValueString)
        {
            //validate that custom values are allowed
            if (partOfMultiSelect == true)
            {
                if (fillInChoice != true) throw new PointBridgeEx("Choice.ChangeSelectionToCustomString(): Custom values are not allowed for field '" + parentMultiSelect.fieldName + "'");
            }
            else
            {
                if (fillInChoice != true) throw new PointBridgeEx("Choice.ChangeSelectionToCustomString(): Custom values are not allowed for field '" + fieldName + "'");
            }

            if (ValidateChoiceString(newValueString) == true) throw new PointBridgeEx("Choice.ChangeSelectionToCustomString(): '" + newValueString + "' is not a custom selection. Consider using Choice.ChangeSelection() method if this is intended.");
            ChangeSelectionNoValidation(newValueString);
        }
        public bool ValidateChoiceString(string str)
        {
            return ValidateChoiceString(str, choices);
        }
        public static bool ValidateChoiceString(string str, string[] choicesArr)
        {
            foreach (string choice in choicesArr)
            {
                if (str == choice) return true;
            }
            return false;
        }
        public override void ForceUpdate()
        {
            if (partOfMultiSelect == true) throw new PointBridgeEx("Choice.ForceUpdate(): Attempt to force update parentItem when this Choice is part of a multi-select");
            parentItem.item[fieldName] = ToSPRepresentation();
        }
        public override void InitFromSPRepresentation(object obj)
        {
            if (obj == null)
            {
                if (emptyAllowed == true)
                {
                    _valueString = null;
                    return;
                }
                else
                {
                    throw new NullEx("Value is null. Use [Property Name]Nullable property if this is intended.");
                }
            }
            _valueString = (string)obj;
        }
        public override object ToSPRepresentation()
        {
            if (isEmpty == true)
            {
                if (emptyAllowed == true) return null;
                else throw new PointBridgeEx("Choice.ToSPRepresentation(): object is not initialized while emptyAllowed is false");
            }
            return valueString;
        }
        public override string ToString()
        {
            if (isEmpty == true) return "<Empty>";
            else return valueString;
        }
        #endregion

        #region Private Helper Methods
        private void ChangeSelectionNoValidation(string newValueString)
        {
            _valueString = newValueString;

            //either update itself or ask parent to update everyhting
            if (partOfMultiSelect != true) ForceUpdate();
            else parentMultiSelect.ForceUpdate();
        }
        #endregion

        #region Public Properties
        public override bool isEmpty
        {
            get
            {
                if (_valueString == null) return true;
                else return false;
            }
        }
        public int selectedChoicesIndex
        {
            get
            {
                if (isEmpty == true) throw new PointBridgeEx("Class Choice: Access to selectedChoicesIndex property while isEmpty is true");
                for (int i = 0; i < choices.Length; i++)
                {
                    if (valueString == choices[i]) return i;
                }
                throw new PointBridgeEx("Class Choice: Unexpected error while accessing selectedChoicesIndex property");
            }
        }
        public string valueString
        {
            get
            {
                if (isEmpty == true) throw new PointBridgeEx("class Choice: Attempting to access 'valueString' while this class container is empty.");
                return _valueString;
            }
        }
        public SPSite site
        {
            get
            {
                return web.Site;
            }
        }
        public SPWeb web
        {
            get
            {
                if (partOfMultiSelect == true) return parentMultiSelect.parentItem.item.Web;
                else return parentItem.item.Web;
            }
        }

        public readonly bool partOfMultiSelect;
        public readonly MultiChoice parentMultiSelect;

        public readonly bool fillInChoice;

        public readonly string[] choices;
        #endregion

        #region Internal Fields
        private string _valueString = null;
        #endregion
    }
}
